<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Helpers\DebugHelper;

class DebugServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        // 注册调试助手
        $this->app->singleton('debug', function () {
            return new DebugHelper();
        });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        // 仅在调试模式下启用
        if (!config('app.debug')) {
            return;
        }

        // 启用 SQL 查询日志
        if (config('database.log_queries', false)) {
            $this->enableQueryLogging();
        }

        // 性能监控
        $this->enablePerformanceMonitoring();

        // 内存使用监控
        $this->enableMemoryMonitoring();
    }

    /**
     * 启用 SQL 查询日志
     */
    protected function enableQueryLogging()
    {
        DB::listen(function ($query) {
            $sql = str_replace('?', '"%s"', $query->sql);
            $fullSql = vsprintf($sql, $query->bindings);
            
            Log::channel('query')->debug('SQL Query', [
                'sql' => $fullSql,
                'raw_sql' => $query->sql,
                'bindings' => $query->bindings,
                'time' => $query->time . 'ms',
                'connection' => $query->connectionName
            ]);

            // 慢查询警告
            if ($query->time > 1000) {
                Log::channel('performance')->warning('Slow Query Detected', [
                    'sql' => $fullSql,
                    'time' => $query->time . 'ms'
                ]);
            }
        });
    }

    /**
     * 启用性能监控
     */
    protected function enablePerformanceMonitoring()
    {
        // 在请求结束时记录性能数据
        register_shutdown_function(function () {
            $executionTime = (microtime(true) - LARAVEL_START) * 1000;
            $memoryUsage = memory_get_usage() / 1024 / 1024;
            $peakMemory = memory_get_peak_usage() / 1024 / 1024;
            $includedFiles = count(get_included_files());

            if ($executionTime > 3000) { // 超过3秒的请求
                Log::channel('performance')->warning('Slow Request', [
                    'execution_time' => round($executionTime, 2) . 'ms',
                    'memory_usage' => round($memoryUsage, 2) . 'MB',
                    'peak_memory' => round($peakMemory, 2) . 'MB',
                    'included_files' => $includedFiles,
                    'url' => request()->fullUrl() ?? 'Console',
                    'method' => request()->method() ?? 'CLI'
                ]);
            }
        });
    }

    /**
     * 启用内存使用监控
     */
    protected function enableMemoryMonitoring()
    {
        // 检查内存使用情况
        register_shutdown_function(function () {
            $memoryLimit = $this->parseMemoryLimit(ini_get('memory_limit'));
            $currentUsage = memory_get_usage();
            $peakUsage = memory_get_peak_usage();
            
            $usagePercentage = ($currentUsage / $memoryLimit) * 100;
            $peakPercentage = ($peakUsage / $memoryLimit) * 100;

            if ($peakPercentage > 80) {
                Log::channel('performance')->warning('High Memory Usage', [
                    'current_usage' => round($currentUsage / 1024 / 1024, 2) . 'MB',
                    'peak_usage' => round($peakUsage / 1024 / 1024, 2) . 'MB',
                    'memory_limit' => round($memoryLimit / 1024 / 1024, 2) . 'MB',
                    'usage_percentage' => round($usagePercentage, 2) . '%',
                    'peak_percentage' => round($peakPercentage, 2) . '%'
                ]);
            }
        });
    }

    /**
     * 解析内存限制值
     *
     * @param string $memoryLimit
     * @return int
     */
    protected function parseMemoryLimit($memoryLimit)
    {
        if ($memoryLimit == -1) {
            return PHP_INT_MAX;
        }

        $unit = strtolower(substr($memoryLimit, -1));
        $value = (int) $memoryLimit;

        switch ($unit) {
            case 'g':
                $value *= 1024;
            case 'm':
                $value *= 1024;
            case 'k':
                $value *= 1024;
        }

        return $value;
    }
}